\section{Платформенное ядро}

\subsection{Основные понятия}

Стаб (Stub)\footnote{Глагол stub - рубить близко к корню...} - высокоуровневая
абстракция платформы. Написан на более удобном языке, но необходимо чтобы
тот язык допускал связывание с C++, на котором написано Core.

\subsection{Консоль}

Стаб обеспечивает низкоуровневую архитектуру ввода-вывода\footnote{Впрочем ввод
весьма ограничен по возможностям, он нужен только интерактивному экрану смерти.}.

Драйвер ввода-вывода определяется параметром командной строки - console. Пока
могу предположить наличие трех драйверов - vga, mda, serial.

Введение драйверной модели ввода-выводв накладывает ограничения на реализацию
экрана смерти. Конечно драйвер может поддерживать манипулирования цветом, но в
любом случае полноэкранный экран смерти придется сменить на консольный.

\subsection{Структура}

Стаб логически подразделяется на несколько частей.

\subsubsection{Менеджер загрузочной информации}

Информация о модулях и разбор их формата - это платформозависимые вещи и
разбираться с ними будет стаб. Для порождения процессов стаб будет использовать
видимую часть ядерного API. после того, как проинициализирует ядро.

Из загрузочной информации стаб извлекает и интерпретирует таблицу символов ядра.

До перехода в страничный режим модули размещаются во временной зоне ядра,
таблица модулей переносится в динамическую память. После включения страничного
режима модули смогут быть проинициализированы.

elf модули преобразованы в процессы. Модули неизвестных типов преобразовываются
в именованные регионы, и приложения смогут получить к ним доступ. Это даст
возможность подгружать данные приложений.

\subsubsection{Менеджер динамической памяти ядра}

Инициализация хипа и размеры памяти для ядра целиком ложаться на плечи стаба.
Так же Stub может иметь реализацию Realloc, если таковая нужна ему для своих
внутренних дел\footnote{Realloc ядру, написанному на c++, не нужен по
определению. Да и текущее ядро использует Realloc только для расширения TSS, что
в новой версии целиком ляжет на плечи стаба.}.

До перехода в страничный режим создается временный хип небольшого размера,
который, после перехода в страничный режим, поглощается ядерным хипом.

\subsubsection{Менеджер ресурсов ядра}

Эта часть следит исключительно за ресурсами ядра, пользовательскими ресурсами
заведует Core. Стоит отметить, что ядро хранит свои ресурсы в своем внутреннем
формате. То есть эти ресурсы не имеют типичных для ресурсов идентификаторов, и
не регистрируются через подсистемы учета ресурсов ядра\footnote{Имеется ввиду
менеджер ресурсов универсального ядра}.

Здесь фиксируется использование ядром страниц.

Специальная функция времени инициализации StubKernelReservePages до перехода в
страничный режим отмечает принадлежащие ядру страницы.

\subsubsection{Менеджер страниц}

Вся память делится на области памяти. Для каждой области заводится массив
описателей входящих в него страниц\footnote{PageInfo.}. Описатель страницы
содержит информацию о физическом адресе страницы, методе доступа, привязке к
ядру, списке инстанций.

Ядро является внутренней сущностью Стаба, и не является ресурсом. Это позволяет
не хранить для ядра страничных инстанций, тем более, что каждая страница может
быть использована в ядре только единажды.

Привязка страниц к ядру осуществляется с помощью линейного адреса. Если адрес
имеет значение, то страница подключена к ядру\footnote{В противном случае он
будет равен нулю. На первый взгляд может показаться, что ноль - не самое удачное
значение для невалидной записи, но я пожалуй могу гарантировать, что по нулевому
адресу никаких страниц замаплено не будет.}. Дополнительно в описателе страницы
устанавливается флаг PFLAGS\_KERNEL. Страницы не подключенные к ядру могут быть
доступны в случае активности процесса - хозяина страниц или путем подключения
этих страниц во временную область ядра.

Ядро может подключать страницы приложений, только в этом случае помимо привязки
к ядру страница будет иметь еще и набор инстанций.

Описатели свободных страниц хранятся в списке.

Для организации страниц в ресурсах будут использоваться инстанции. Базовый
формат инстанции так же предоставляется Стабом\footnote{Core может расширить
этот формат по необходимости.}. Стаб заведует списками инстанций у страниц, но
не определяет механизмы связи инстанций с ресурсами.

\subsubsection{Менеджер задач}

Платформенное ядро предоставляет возможности манипулирования задачами (StubTask).

Задачи платформенного ядра скрывают все платформенные особенности организации
задач, и предоставляют переносимому ядру удобный интерфейс управления. Который
состоит из следующих функций:

\begin{verbatim}
StubTask *StubTaskCreate (laddr_t entry);
StubTaskDestroy (StubTask *task);
StubTaskExcexute (StubTask *task);
\end{verbatim}

Задачи платформенного ядра не обязательно должны быть ассоциированы с ресурсами.
Вполне возможны служебные задачи платформенного ядра.

Для переносимого ядра структура StubTask обязана содержать указатель thread.
Этот указатель переносимым ядром будет преобразован в указатель на CoreResourceThread.

\subsubsection{Драйвер контроллера прерываний}

Сигналы прерываний доводятся до сведения Core в виде ресурсных событий. Для
реализации этого необходимо обеспечить механизм регистрации ожидающих ресурсов
на прерываниях.

Хотя Core для этого могло бы иметь псевдо ресурсы. На которых легко строить
механизмы ожиданий, в то время как Стабу необходимо знать только идентификатор
псевдоресурса\footnote{Стоит отметить, что ядру нет никакой необходимости в
отдельном типе ресурсов для прерываний.}.

В принципе мне подумалось тут, что ресурсы прерываний могли бы
инициализироваться процессами. Предусмотреть специальную модификацию, которая
будет переводить кастомный ресурс в разряд прерываний, и соответственно биндить
к стабу\footnote{Если конечно соответствующее прерывание доступно и ранее не
занято.}.

\subsubsection{Драйвер системного таймера}

\subsubsection{Системные вызовы}

Системные вызовы почти немедленно пробрасываются в Core.

\subsection{Stub для IA32}

\subsubsection{Типы}

\begin{description}
\item[unsigned long] id\_t, laddr\_t, size\_t
\item[unsigned long long] paddr\_t, sizex\_t
\end{description}

\subsubsection{Инициализация}

Прежде всего необходимо почистить bss, gcc заносит в bss даже данные,
проинициализированные в коде нулем, а при старте оказывается что там вовсе не
ноль. Поэтому инициализация нулем вкупе с очисткой bss при старте даст гарантию
нулевости переменных.

Потом у каждой подсистемы запускается инициализация.

Обрабатываем командную строку ядра, и извлекаем из нее переданные параметры, они
могут повлиять на дальнейшую инициализацию.

Инициализируем временный хип. Память для временного хипа выбирается после
модулей. А длинна выбирается такой, чтобы он не выходил за пределы текущего
блока памяти. Хотя вряд ли он понадобиться такой большой, необходимый для
инициализации размер вычисляется по формуле:
$$h = {msz \over PAGE\_SIZE} * sizeof(PageInfo) + mods * 1KiB + 128KiB$$
где msz - это размер памяти, выровненный по границам страниц, mods - количество
модулей, 128Kib - резерв на всякие мелочи.

С помощью загрузочной информации grub получаем доступ к символам ядра, все
символы переносятся в динамическую память ядра и будут использованы в случае
срабатывания синего экрана смерти. Именно поэтому их надо обработать по
возможности раньше.

Иниуиализируется GDT и IDT. По логике вещей дескрипторные таблицы необходимо
инициализировать после того, как будет осуществлен переход в страничный режим.
Потому, что сегментные механизмы защиты работают на уровне линейной памяти. Но в
нашем случае физические и линейные адреса таблиц совпадают, и нет необходимости
переживать но проинициализировав IDT мы получаем возможность использовать
обработчики исключений, и чем раньше это будет сделано, тем лучше.

Инициализируются списки описателей страниц (PageInfo). На этом этапе все
страницы отмечаются как свободные и заносятся в список свободных страниц.

Резервируются страницы ядра которые входят в код ядра, в данные ядра и в область
временной динамической памяти. Эти страницы соотносятся со своими будующими
линейными адресами для того, чтобы при инициализации страничного преобразования
мы могли без лишних проблем сразу расположить эти страницы в соответствующих
местах линейной памяти.

Резервируется память, в которой располагаются модули. Информация о расположеении
модулей переносится в динамическую памяти и модифицируется в соответствии с
линейным расположением модулей. После перехода в страничный режим модули будут проинициализированы и используемая память будет отключена от ядра.


\subsubsection{Распределение памяти системы}

{\parskip 0pt \hrule \vrule Память ядра\hfill \vrule \hrule}

\subsubsection{Задачи}

Задачи занимают некоторое количество памяти для служебных целей. Это страница
стека нулевого кольца, каталог страниц и таблицы страниц стека. 12Kib на нить
минимум...

Страницы стека выделяются нити на верхнем уровне логики по исключениям. Таблицы
страниц кода и данных принадлежат процессу, который сам по себе существует
только на верхнем уровне.

У переносимого ядра должна быть функция исключения по памяти. в нее будет
передаваться таск, а возвращаться будет PageInfo. Через эту же функцию нити
будут набиваться страницами в процессе инициализации.

Поскольку TSS - понятие растяжимое, следовательно, оно может, в результате
работы realloc, менять свое месторасположение. С другой стороны стабу дела нету
до того, как нити организованы в Core. Следовательно в стабе для нити необходима
своя организационная структура. Это позволит скрыть от ядра манипуляции с TSS, и
предоставить некую сущность, позволяющую однозначно идентифицировать нить с
обоих сторон.

Переносимое ядро автоматически распределяет некорторое доступное количество
дескрипторов задач между активными задачами. Если какая-либо задача еще не имеет
дескриптора выбирается свободный дескриптор из имеющихся, в случае отсутствия
свободных освобождается наиболее давно не использующийся дескриптор и входящая
задача занимает его. Этот механизм носит название Слоты задач.

\subsection{Stub для Linux}

Этот стаб написан на C++. Для своей установки требует отдельный рут и отдельную
конфигурацию сборки, но зато позволяет с большим успехом отлаживать Core.

\subsubsection{Типы}

id\_t и size\_t стаб использует стандартные.
